package fcnet

import (
	"fmt"
	"net"
	"os"
	"os/signal"
	"sync"
	"sync/atomic"
	"time"

	"gitee.com/fcsvr/fc/fclog"
)

type Server struct {
	Name   string
	IPVer  string
	IP     string
	Port   int
	IfRun  bool
	ConnID atomic.Uint64

	wp sync.WaitGroup
}

func NewServer() *Server {
	s := &Server{}
	s.IfRun = true
	return s
}

func (this *Server) Start() {
	fclog.Info("Server = %s, Start Listen at IP = %s, Port = %d", this.Name, this.IP, this.Port)

	//开启消息处理管理器的工作池
	SvrMgr.MsgHandle().StartWorkerPool()

	//解析tcp地址,监听
	addr, err := net.ResolveTCPAddr(this.IPVer, fmt.Sprintf("%s:%d", this.IP, this.Port))
	if err != nil {
		fclog.Error("Server resolve add err = %v", err)
		return
	}

	listenner, err := net.ListenTCP(this.IPVer, addr)
	if err != nil {
		fclog.Error("Server listen err = %v", err)
		return
	}

	fclog.Info("Server listen now...")

	timeDead := time.Now()
	for this.IfRun {
		//等待cli的连接
		timeDead = timeDead.Add(1 * time.Second)
		listenner.SetDeadline(timeDead)
		tcpConn, err := listenner.AcceptTCP()
		if err != nil {
			//fclog.Error("Server accept err = %v", err)
			continue
		}

		this.ConnID.Add(1)
		fclog.Debug("Conn len = %d", SvrMgr.Conn().Len())
		fcConn := NewConn(tcpConn, int(this.ConnID.Load()))
		SvrMgr.Conn().AddConn(fcConn)
		fcConn.Start()
	}
	SvrMgr.Sync().ConnWp().Done()
	fclog.Info("Server Start accept end")
}

func (this *Server) Stop() {
	SvrMgr.Conn().ClearAllConn()
	fclog.Info("Server Stop Server = %s", this.Name)
	this.IfRun = false
	SvrMgr.Sync().ConnWp().Wait()
	fclog.Info("Server Stop end")
}

func (this *Server) LoadConfig() {
	this.Name = SvrMgr.ConfigSvr().Name
	this.IPVer = SvrMgr.ConfigSvr().IPVer
	this.IP = SvrMgr.ConfigSvr().IP
	this.Port = SvrMgr.ConfigSvr().TCPPort
}

func (this *Server) Serve() {
	this.LoadConfig()
	SvrMgr.Sync().ConnWp().Add(1)
	go this.Start()

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)
	<-signalChan
	fclog.Info("Server Serve recv signal interrupt")

	this.Stop()
}

func (this *Server) AddMsgHandle(msgid uint32, handle ItfHandle, arg any) {
	SvrMgr.MsgHandle().AddHandle(msgid, handle, arg)
}

func (this *Server) GetMsgHandle(msgid uint32) ItfHandle {
	return SvrMgr.MsgHandle().GetHandle(msgid)
}

func (this *Server) AddInitHandle(msgid uint32, handle ItfHandle) {
	SvrMgr.MsgHandle().AddInitHandle(msgid, handle)
}

func (this *Server) AddFiniHandle(msgid uint32, handle ItfHandle) {
	SvrMgr.MsgHandle().AddFiniHandle(msgid, handle)
}

func (this *Server) PushMsg(msgid uint32, msgbody []byte, connids ...int) error {
	return SvrMgr.Conn().PushMsg(msgid, msgbody, connids...)
}

func (this *Server) Load() {
	SvrMgr.Config().Load()
}
